Skip to content

fix non-copyable derived dependency passed as base-class reference (issue #467)#679

Open
PavelGuzenfeld wants to merge 1 commit into
boost-ext:masterfrom
PavelGuzenfeld:fix/issue-467-non-copyable-derived-dep
Open

fix non-copyable derived dependency passed as base-class reference (issue #467)#679
PavelGuzenfeld wants to merge 1 commit into
boost-ext:masterfrom
PavelGuzenfeld:fix/issue-467-non-copyable-derived-dep

Conversation

@PavelGuzenfeld
Copy link
Copy Markdown
Contributor

Fixes #467.

Root cause

When an action takes Base& but the sm<> constructor receives Derived& (e.g. NiceMock<T>, or any type with a deleted copy constructor), the pool init copy-constructor called try_get<Base>(&source_pool). The source pool held pool_type<Derived&>, not pool_type<Base&>, so the exact-match overload was not viable. The fallback try_get(...) returned missing_ctor_parameter<Base>, which tried to default-construct Base and bind it to Base& — which fails (cannot bind a reference to a temporary).

This regression was introduced in v1.1.4 when missing_ctor_parameter was added.

Fix

Add two covariant try_get overloads constrained on is_base_of<T,D> && !is_same<T,D>:

template <class T, class D, REQUIRES(is_base_of<T,D> && !is_same<T,D>)>
constexpr T& try_get(const pool_type<D&>*);

template <class T, class D, REQUIRES(is_base_of<T,D> && !is_same<T,D>)>
constexpr const T& try_get(const pool_type<const D&>*);

Both return the stored D& / const D& value, which implicitly upcasts to T& / const T&. The !is_same<T,D> constraint prevents ambiguity with the existing exact-match overloads.

Test

Added non_copyable_derived_dep_as_base_ref to test/ft/dependencies.cpp: passes derived467 (inherits base467, copy ctor deleted) to sm<c467> whose action takes base467&.

…ssue boost-ext#467)

When an action or guard takes Base& but the sm<> ctor receives Derived& (e.g.
NiceMock<T>, any type with a deleted copy constructor), the pool init
copy-constructor called try_get<Base>() which found nothing in the source pool
(which held Derived&) and fell back to missing_ctor_parameter<Base>.
missing_ctor_parameter tried to default-construct Base and bind it to Base& —
which fails (can't bind a reference to a temporary).

Root cause: try_get had no covariant overloads; lookup was exact-type only.

Fix: add two new try_get overloads constrained on is_base_of<T,D>:
  try_get<T>(pool_type<D&>*)       -> T&
  try_get<T>(pool_type<const D&>*) -> const T&
Both return the stored D& / const D& value, which implicitly converts to
the base-class reference T& / const T&.  is_same<T,D> is excluded to
prevent ambiguity with the existing exact-match overloads.

Regression test: non_copyable_derived_dep_as_base_ref in
test/ft/dependencies.cpp — passes derived467 (inherits base467,
deleted copy ctor) to sm<c467> whose action takes base467&.
@PavelGuzenfeld PavelGuzenfeld force-pushed the fix/issue-467-non-copyable-derived-dep branch from 9ac2e3b to 449dbd7 Compare May 24, 2026 21:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Google's NiceMock<MyMock> dependencies fail to compile if dependency is passed as reference template parameter

1 participant